package com.example.demo.controller;

import com.example.demo.constant.ItemFromType;
import com.example.demo.dto.ItemDTO;
import com.example.demo.dto.MixinResponse;
import com.example.demo.model.Item;
import com.example.demo.repository.ItemModel;
import com.example.demo.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;


@RestController
@RequestMapping("/mixin")
public class MixinController {

    @Resource
    private ItemModel itemModel;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @PostMapping("/item")
    public ResponseEntity<MixinResponse> addItem(@RequestParam("item") String item,
                                                 @RequestParam("name") String name,
                                                 @RequestParam("hot") Boolean hot) {

        if (StringUtil.isEmpty(item)) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 内容不能为空"),
                    HttpStatus.OK);
        }

        if (StringUtil.isEmpty(name)) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 名称不能为空"),
                    HttpStatus.OK
            );
        }

        if (hot == null) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 预热缓存开关不能为空"),
                    HttpStatus.OK
            );
        }


        try {
            this.itemModel.insertItem(new Item(name, item));
        } catch (Exception e) {
            this.logger.error(String.format("添加数据错误: %s", e.getMessage()));
            return new ResponseEntity<>(
                    new MixinResponse("5000", "服务器错误"),
                    HttpStatus.OK);
        }

        boolean cached = false;

        if (hot) {
            try {
                this.stringRedisTemplate.opsForValue().set(name.trim(), item.trim(), 15, TimeUnit.SECONDS);
                cached = true;
            } catch (Exception e) {
                this.logger.error(String.format("添加缓存错误: %s", e.getMessage()));
            }
        }

        if (hot) {
            if (cached) {
                return new ResponseEntity<>(
                        new MixinResponse("1000", "完成")
                                .withData(
                                        new ItemDTO(
                                                name, item, ItemFromType.CACHE)
                                ),
                        HttpStatus.OK);
            } else {
                return new ResponseEntity<>(
                        new MixinResponse("1500", "完成")
                                .withData(
                                        new ItemDTO(
                                                name, item, ItemFromType.DATABASE)
                                ),
                        HttpStatus.OK);
            }
        } else {
            return new ResponseEntity<>(
                    new MixinResponse("1000", "完成")
                            .withData(
                                    new ItemDTO(
                                            name, item, ItemFromType.DATABASE)
                            ),
                    HttpStatus.OK);
        }
    }

    @DeleteMapping("/item")
    public ResponseEntity<MixinResponse> removeItem(@RequestParam("name") String name) {

        if (StringUtil.isEmpty(name)) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 名称不能为空"),
                    HttpStatus.OK
            );
        }

        try {
            this.itemModel.deleteItemByName(name);
        } catch (Exception e) {
            this.logger.error(String.format("删除数据错误: %s", e.getMessage()));
            return new ResponseEntity<>(new MixinResponse("5000", "服务器错误"), HttpStatus.OK);
        }

        boolean cacheDeleted = false;

        try {
            this.stringRedisTemplate.opsForValue().getAndDelete(name);
            cacheDeleted = true;
        } catch (Exception e) {
            this.logger.error(String.format("删除缓存错误: %s", e.getMessage()));
        }

        if (!cacheDeleted) {
            return new ResponseEntity<>(new MixinResponse("1500", "完成"), HttpStatus.OK);
        }

        return new ResponseEntity<>(new MixinResponse("1000", "完成"), HttpStatus.OK);
    }

    @PutMapping("/item")
    public ResponseEntity<MixinResponse> updateItem(@RequestParam("item") String item,
                                                    @RequestParam("name") String name) {

        if (StringUtil.isEmpty(item)) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 内容不能为空"),
                    HttpStatus.OK);
        }

        if (StringUtil.isEmpty(name)) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 名称不能为空"),
                    HttpStatus.OK
            );
        }

        boolean cacheDeleted = false;

        try {
            this.stringRedisTemplate.opsForValue().getAndDelete(name);
            cacheDeleted = true;
        } catch (Exception e) {
            this.logger.error(String.format("更新时删除缓存错误: %s", e.getMessage()));
        }

        try {
            this.itemModel.updateItemByName(name, item);
        } catch (Exception e) {
            this.logger.error(String.format("更新数据错误: %s", e.getMessage()));
            return new ResponseEntity<>(new MixinResponse("5000", "服务器错误"), HttpStatus.OK);
        }

        if (cacheDeleted) {
            return new ResponseEntity<>(new MixinResponse("1000", "完成"), HttpStatus.OK);
        }

        return new ResponseEntity<>(new MixinResponse("1500", "完成"), HttpStatus.OK);
    }
    @GetMapping("/item")
    public ResponseEntity<MixinResponse> getItemByName(@RequestParam("name") String name) {

        if (StringUtil.isEmpty(name)) {
            return new ResponseEntity<>(
                    new MixinResponse("4000", "参数错误, 名称不能为空"),
                    HttpStatus.OK
            );
        }


        String cached = null;
        try {
            cached = this.stringRedisTemplate.opsForValue().get(name);
        } catch (Exception e) {
            this.logger.error(String.format("从缓存加载数据失败: %s", e.getMessage()));
        }

        if (cached != null) {
            return new ResponseEntity<>(
                    new MixinResponse("1000", "完成").withData(
                            new ItemDTO(name, cached, ItemFromType.CACHE)),
                    HttpStatus.OK);
        }

        Item result = null;

        try {
            result = this.itemModel.selectItemByName(name);
        } catch (Exception e) {
            this.logger.error(String.format("获取数据错误: %s", e.getMessage()));
            return new ResponseEntity<>(new MixinResponse("5000", "服务器错误"), HttpStatus.OK);
        }

        if (result == null) {
            return new ResponseEntity<>(
                    new MixinResponse("1000", "完成").withData(new ItemDTO()),
                    HttpStatus.OK
            );
        }

        boolean setCached = false;

        try {
            this.stringRedisTemplate.opsForValue().set(result.getName(), result.getItem(), 15, TimeUnit.SECONDS);
            setCached = true;
        } catch (Exception e) {
            this.logger.error(String.format("拷贝到缓存错误: %s", e.getMessage()));
        }

        if (setCached) {
            return new ResponseEntity<>(
                    new MixinResponse("1000", "完成")
                            .withData(
                                    new ItemDTO(result, ItemFromType.DATABASE))
                    , HttpStatus.OK);
        }

        return new ResponseEntity<>(
                new MixinResponse("1500", "完成")
                        .withData(
                                new ItemDTO(result, ItemFromType.DATABASE)),
                HttpStatus.OK);
    }
}
